﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MsTestContextPlugin.cs" company="">
// </copyright>
// <summary>
//   The ms test context plugin.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace MsTestContext.Generator.SpecflowPlugin
{
    using System;
    using System.CodeDom;

    using TechTalk.SpecFlow.Generator;
    using TechTalk.SpecFlow.Generator.Plugins;
    using TechTalk.SpecFlow.Generator.UnitTestProvider;
    using TechTalk.SpecFlow.Utils;

    /// <summary>
    ///     The ms test context plugin.
    /// </summary>
    public class MsTestContextPlugin : IGeneratorPlugin
    {
        #region Public Methods and Operators

        /// <summary>
        /// The generator plugin events on customize dependencies.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="customizeDependenciesEventArgs">
        /// The customize dependencies event args.
        /// </param>
        public virtual void GeneratorPluginEventsOnCustomizeDependencies(
            object sender, 
            CustomizeDependenciesEventArgs customizeDependenciesEventArgs)
        {
            string unitTestProviderName =
                customizeDependenciesEventArgs.SpecFlowProjectConfiguration.GeneratorConfiguration
                    .GeneratorUnitTestProvider;

            if (unitTestProviderName.Equals("mstest", StringComparison.InvariantCultureIgnoreCase)
                || unitTestProviderName.Equals("mstest.2010", StringComparison.InvariantCultureIgnoreCase))
            {
                customizeDependenciesEventArgs.ObjectContainer
                    .RegisterTypeAs<MsTestContextGeneratorProvider, IUnitTestGeneratorProvider>();
            }
        }

        /// <summary>
        /// The initialize.
        /// </summary>
        /// <param name="generatorPluginEvents">
        /// The generator plugin events.
        /// </param>
        /// <param name="generatorPluginParameters">
        /// The generator plugin parameters.
        /// </param>
        public void Initialize(
            GeneratorPluginEvents generatorPluginEvents, 
            GeneratorPluginParameters generatorPluginParameters)
        {
            generatorPluginEvents.CustomizeDependencies += this.GeneratorPluginEventsOnCustomizeDependencies;
        }

        #endregion
    }

    /// <summary>
    ///     The ms test context generator provider.
    /// </summary>
    public class MsTestContextGeneratorProvider : MsTest2010GeneratorProvider
    {
        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="MsTestContextGeneratorProvider"/> class.
        /// </summary>
        /// <param name="codeDomHelper">
        /// The code dom helper.
        /// </param>
        public MsTestContextGeneratorProvider(CodeDomHelper codeDomHelper)
            : base(codeDomHelper)
        {
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The set test class.
        /// </summary>
        /// <param name="generationContext">
        /// The generation context.
        /// </param>
        /// <param name="featureTitle">
        /// The feature title.
        /// </param>
        /// <param name="featureDescription">
        /// The feature description.
        /// </param>
        public override void SetTestClass(
            TestClassGenerationContext generationContext, 
            string featureTitle, 
            string featureDescription)
        {
            base.SetTestClass(generationContext, featureTitle, featureDescription);

            // Declare local variable
            var mstestContextField = new CodeMemberField
                                         {
                                             Attributes =
                                                 MemberAttributes.Private | MemberAttributes.Final, 
                                             Name = "myTestContext", 
                                             Type = new CodeTypeReference(TESTCONTEXT_TYPE), 
                                         };

            generationContext.TestClass.Members.Add(mstestContextField);

            // Declare assignment method
            var mstestContextProperty = new CodeMemberProperty
                                            {
                                                Name = "TestContext", 
                                                Type = new CodeTypeReference(TESTCONTEXT_TYPE), 
                                                Attributes = MemberAttributes.Public
                                            };

            mstestContextProperty.GetStatements.Add(
                new CodeMethodReturnStatement(new CodeVariableReferenceExpression("myTestContext")));

            mstestContextProperty.SetStatements.Add(
                new CodeAssignStatement(
                    new CodeVariableReferenceExpression("myTestContext"), 
                    new CodePropertySetValueReferenceExpression()));
            mstestContextProperty.SetStatements.Add(
                new CodeAssignStatement(
                    new CodeVariableReferenceExpression("FeatureContext.Current[\"TestContext\"]"), 
                    new CodePropertySetValueReferenceExpression()));

            generationContext.TestClass.Members.Add(mstestContextProperty);
        }

        #endregion
    }
}